
package scalaExec.scalaLab;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;

import scalaExec.gui.*;
import scalaExec.Interpreter.GlobalValues;

import scalaExec.Wizards.*;
import java.awt.Color;
import java.lang.reflect.*;
import scalaExec.ClassLoaders.ExtensionClassLoader;

class scalalabScriptsPathsAction extends AbstractAction  {
       scalalabScriptsPathsAction()  { super(" Browse ScalaLabPath / Remove ScalaLabPath components"); }
       
         public void actionPerformed(java.awt.event.ActionEvent evt) {
                       JFrame paramFrame = new JFrame("Browse ScalaLabPath / Remove ScalaLabPath components");
                       paramFrame.setSize((int)(GlobalValues.scalalabMainFrame.xSizeMainFrame*0.3), (int)(GlobalValues.scalalabMainFrame.ySizeMainFrame*0.3));
                       scalaSciScriptsPathsTree paramTree = new scalaSciScriptsPathsTree();
                       paramTree.buildVariablesTree();
                       JPanel helpPanel = new JPanel();
                       JLabel helpLabelBrowse = new JLabel("The parameter frame allows to browse on the ScalalClassPath by clicking upon them");
                       JLabel helpLabelDelete = new JLabel("You can remove the selected ScalaClasspath component by pressing the DEL key");
                       JLabel helpLabelInsert = new JLabel("You can append new directories to the ScalaClasspath from the ScalalabExplorer");
                       helpPanel.setLayout(new GridLayout(3,1));
                       helpPanel.add(helpLabelBrowse);
                       helpPanel.add(helpLabelDelete);
                       helpPanel.add(helpLabelInsert);

                       JPanel paramPanel = new JPanel();
                       paramPanel.add(helpPanel);
                        paramPanel.add(paramTree);
                       paramFrame.add(paramPanel);
                       paramFrame.setVisible(true);
                       	 }
                   }
  
                 
   
   
           
           
 class  loadAllClassesFromJLabClassPathAction extends  AbstractAction    {

    public loadAllClassesFromJLabClassPathAction() {
        super("Load  All Classes from ScalaSciClassPath");
    }
    
    public  void actionPerformed(ActionEvent e)  {
        
                 ExtensionClassLoader  extClassLoader = new ExtensionClassLoader(GlobalValues.ScalaSciClassPath);
                 
                 Enumeration enumElem = GlobalValues.ScalaSciClassPathComponents.elements();
        while  (enumElem.hasMoreElements())  {   // for all ScalaSciClassPath Components
         	    Object next = (Object)enumElem.nextElement();
                    String pathName = next.toString().trim();
                     File dir = new File(pathName);
                     String[] files = dir.list();
                     if (files != null) {  
              for (int k=0; k<files.length; k++)  {   // for all files in the current directory
                      String currentFile = files[k]; 
                      
                    int idx  = currentFile.indexOf(".class");
                    int idxOfBackup = currentFile.indexOf("~");  // avoid using backup UNIX style files
                    if (idx != -1 && idxOfBackup==-1)  {  // file is a .class file
                        String  classNameToLoad = currentFile.substring(0, idx);
                        try {
                        Class  loadedClass = extClassLoader.loadClass(classNameToLoad);
                        Method m = null;
                        try {
                            m = loadedClass.getMethod("main", scalaExec.scalaLab.scalaLab.formals);
                        }
                        catch (NoSuchMethodException exc) {
                            System.out.println(" no main in  "+classNameToLoad);
                            exc.printStackTrace();
                            break;
                        }
                        
                        try {
                            m.invoke(null, scalaExec.scalaLab.scalaLab.actuals);
                        }
                        catch (Exception exc)  {
                            exc.printStackTrace();
                          }
                        }
                        
                        catch (ClassNotFoundException ex)  {
                            System.out.println("Class: "+classNameToLoad+" not found");
                            ex.printStackTrace();
                        } 
                        System.out.println("pathName ="+pathName);
                    }   // file is a .class file
                    
                    int javaIdx = currentFile.indexOf(".java");
                    idxOfBackup = currentFile.indexOf("~");
                    if (javaIdx != -1 && idxOfBackup==-1)  {
                      JavaCompile javaCompileObj = new JavaCompile();
        
         String packageName = "";
         String javaFile = pathName+File.separatorChar+currentFile;  
         boolean compilationResult = javaCompileObj.compileFile(javaFile);
         if (compilationResult == true)  // success
         {
             System.out.println("Compilation success for file "+packageName+"."+javaFile);
             int lastPos = javaFile.length()-5;  // for ".java"
             String  classNameToLoad = javaFile.substring(javaFile.lastIndexOf(File.separatorChar)+1, lastPos);
                       
           try {   // try to load the class
                        Class  loadedClass = extClassLoader.loadClass(classNameToLoad);
                        Method m = null;
                        try {
                            m = loadedClass.getMethod("main", scalaExec.scalaLab.scalaLab.formals);
                        }
                        catch (NoSuchMethodException exc) {
                            System.out.println(" no main in  "+classNameToLoad);
                            exc.printStackTrace();
                            break;
                        }
                        
                        try {
                            m.invoke(null, scalaExec.scalaLab.scalaLab.actuals);
                        }
                        catch (Exception exc)  {
                            exc.printStackTrace();
                          }
           }  // try to load the class
                        
                        catch (ClassNotFoundException ex)  {
                            System.out.println("Class: "+classNameToLoad+" not found");
                            ex.printStackTrace();
                        } 
                        System.out.println("pathName ="+pathName);
                   
            }   // compilation result success
         }    // javaIdx != -1
              }   // for all files in the current directory
                                            }   // files != null
        }  // for all ScalaSciClassPath Components
    }    
 }                    

                
   
   
       class FontAdjusterAction extends AbstractAction  {
        public void actionPerformed(ActionEvent e) {
 JFontChooser  myFontChooser = new JFontChooser(GlobalValues.scalalabMainFrame);
 myFontChooser.setVisible(true);
 Font choosingFont = myFontChooser.getFont();
 Color fontColorChoosed =  myFontChooser.getForegroundColor();
 int rgbAlpha = fontColorChoosed.getAlpha(), rgbRed = fontColorChoosed.getRed(), rgbBlue = fontColorChoosed.getBlue(), rgbGreen = fontColorChoosed.getGreen();
 GlobalValues.scalalabMainFrame.scalalabConsole.setFont(choosingFont);
 GlobalValues.scalalabMainFrame.scalalabConsole.setForeground(myFontChooser.getForegroundColor());
 GlobalValues.settings.setProperty("alphaProp",  Integer.toString(rgbAlpha));
 GlobalValues.settings.setProperty("redProp",  Integer.toString(rgbRed));
 GlobalValues.settings.setProperty("greenProp",  Integer.toString(rgbGreen));
 GlobalValues.settings.setProperty("blueProp",  Integer.toString(rgbBlue));

 int  isBold = 0;   if (choosingFont.isBold()) isBold = 1;
 int  isItalic = 0;   if (choosingFont.isItalic()) isItalic = 1;
 GlobalValues.settings.setProperty("isBoldProp", Integer.toString(isBold));
 GlobalValues.settings.setProperty("isItalicProp", Integer.toString(isItalic));
         }
       }

     
       class LookAndFeelAdjusterAction extends AbstractAction {
           public void actionPerformed(ActionEvent e) {
               JFrame lookAndFeelFrame = new JFrame("Configure Look and Feel");
               JButton nativeLookAndFeel = new JButton("Native Look and Feel");
               nativeLookAndFeel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
           try {
            String sysLookAndFeel = UIManager.getSystemLookAndFeelClassName();
            UIManager.setLookAndFeel(sysLookAndFeel);
            scalaExec.scalaLab.scalaLab.updateTree();
	} catch (Exception exc) {
	    System.err.println("Error loading L&F: " + exc);
	}
      }
        });
        
        JPanel lookAndFeelConfigPanel = new JPanel();
        
          JButton crossPlatformLookAndFeel = new JButton("Cross Platform Look and Feel");
               crossPlatformLookAndFeel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
           try {
            String  crossPlatformLookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
            UIManager.setLookAndFeel(crossPlatformLookAndFeel);
            scalaExec.scalaLab.scalaLab.updateTree();
	} catch (Exception exc) {
	    System.err.println("Error loading L&F: " + exc);
	}
      }
        });

        lookAndFeelConfigPanel.add(nativeLookAndFeel);
        lookAndFeelConfigPanel.add(crossPlatformLookAndFeel);
        lookAndFeelFrame.add(lookAndFeelConfigPanel);
        lookAndFeelFrame.setSize(300, 200);
        lookAndFeelFrame.setVisible(true);
           }
       }
       
       
   class browseFileSysForPaths extends AbstractAction {

    public browseFileSysForPaths() {
      super("Browse File System For Updating Class Paths");
    }
       
    @Override
       public void actionPerformed(ActionEvent e) {
                           SwingUtilities.invokeLater(new Runnable() {
            @Override
           public void run() {  // run in  */
     String initialSelectionDir = "/";
     if (GlobalValues.hostIsUnix==false)
         initialSelectionDir = "c:\\";
     
     initialSelectionDir =    JOptionPane.showInputDialog("Specify the root of the file system to browse", initialSelectionDir);
     
                try {
                FileTreeExplorer ftree = new FileTreeExplorer(initialSelectionDir);
                GlobalValues.currentFileExplorer = ftree;
                JFrame treeFrame = new JFrame("Select directory");
                treeFrame.add(new JScrollPane(ftree.pathsTree));
                treeFrame.setSize(600, 500);
                treeFrame.setVisible(true);
                }
                catch (FileNotFoundException fnfexce) { 
                    System.out.println("File not found exception in FileTreeExplorer");
                    fnfexce.printStackTrace();
                } 
    }
                           });
    
    }
   }
   
   

   // saves the user configuration parameters
 class saveConfigAction extends AbstractAction  {
     saveConfigAction()  { super("Save Configuration Parameters (ScalaSci CLASSPATH etc"); }
     
     public void actionPerformed(ActionEvent e)  {
            SwingUtilities.invokeLater(new Runnable() {

    public void run() {
        try {
    JFileChooser  chooser = new JFileChooser(GlobalValues.workingDir);
    chooser.setDialogTitle("Browse filesystem for saving properties file");
    int retVal = chooser.showSaveDialog(GlobalValues.scalalabMainFrame);
    if (retVal == JFileChooser.APPROVE_OPTION) { 
      File selectedFile = chooser.getSelectedFile();
      String outPropFile = selectedFile.getAbsolutePath();
      FileOutputStream outFile= new FileOutputStream(outPropFile);
      GlobalValues.passPropertiesFromWorkspaceToSettings(GlobalValues.settings);  // update properties to the current values kept in workspace
      GlobalValues.settings.store(outFile, "Saved scalaLab global conf parameters");
      outFile.close();
      }
     }
     catch (IOException e) {
    	 e.printStackTrace();
       }
              
              }
        });
     }
 }              
   
 class loadConfigAction extends AbstractAction  {
      loadConfigAction()  { super("Load Configuration Parameters (ScalaSci CLASSPATH etc)");  }
        
       public void actionPerformed(ActionEvent e)  {
             SwingUtilities.invokeLater(new Runnable() {

            public void run() {
       try {
    GlobalValues.clearProperties();
    JFileChooser  chooser = new JFileChooser(GlobalValues.workingDir);
    chooser.setDialogTitle("Browse filesystem for properties file");
    int retVal = chooser.showOpenDialog(GlobalValues.scalalabMainFrame);
    if (retVal == JFileChooser.APPROVE_OPTION) { 
    File selectedFile = chooser.getSelectedFile();
    String inPropFile = selectedFile.getAbsolutePath();
    FileInputStream inFile = new FileInputStream(inPropFile);
    GlobalValues.settings.clear();    // clear previous configuration settings
    GlobalValues.settings.load(inFile);   // load the new configuration settings
    inFile.close();
    GlobalValues.passPropertiesFromSettingsToWorkspace(GlobalValues.settings); // update workspace variables from the properties 
    GlobalValues.scalalabMainFrame.scalalabConsole.interpreterWithAppendedCP(GlobalValues.ScalaSciClassPathComponents);   // return an interpreter with appended classpath
    // reload the toolboxes specified in the configuration file
 Enumeration <String>  scalaSciComps = GlobalValues.ScalaSciClassPathComponents.elements();
 String [] allPaths = new String[100];
 int pathCnt=0;
 while (scalaSciComps.hasMoreElements()) {
     String   currentElem = scalaSciComps.nextElement().trim();
     if (currentElem.endsWith((".jar"))) { // a jar file is treated as a toolbox
         if ( scalaSciToolboxes.scalaSciToolboxesLoadedListModel.contains(currentElem)== false)  { // toolbox was not already loaded
            scalaSciCommands.BasicCommands.appendClasspath(currentElem);
            GlobalValues.extensionClassLoader = new ExtensionClassLoader(currentElem, (ClassLoader) GlobalValues.scalalabMainFrame.scalalabConsole.scalaInterpreter.getInterpreterClassLoader());
            int numClassesOfToolbox  = GlobalValues.ScalaToolboxesLoader.scanAllToolboxClasses(currentElem);
            scalaSciToolboxes.scalaSciToolboxesLoadedListModel.addElement(currentElem);
            System.out.println("numClassesOfToolbox loaded from the toolbox of the configuration file:  "+currentElem+", = "+numClassesOfToolbox);
         }
     }
     else  { // a user specified class path
         allPaths[pathCnt++] = currentElem;   
         }

     
     scalaSciCommands.BasicCommands.appendClasspaths(allPaths);
     
     GlobalValues.scalalabMainFrame.explorerPanel.buildClassScriptPathsTree();
            
    scalaExec.scalaLab.scalaLab.updateTree();
    scalaExec.scalaLab.scalaLab.outerPane.revalidate();
      }
    }  //  JFileChooser.APPROVE_OPTION
    } catch (IOException ioe) {
    	 ioe.printStackTrace();
       }   // try
    
          }
        });
       }
      }
 
 class configAlphaAction extends AbstractAction {
     configAlphaAction() { super("Configuring alpha - transparency parameter"); }
     public void actionPerformed(ActionEvent e) {
                 
  SwingUtilities.invokeLater(new Runnable() {
public void run() {  // run in  */
      
String newAlpha = JOptionPane.showInputDialog("Alpha Parameter",  GlobalValues.alphaComposite);
GlobalValues.alphaComposite = Float.valueOf(newAlpha);
}
});
                 }
      
        
     }
 

 class promptConfigAction extends AbstractAction { 
     promptConfigAction()   {super("Switches Display/Hide working directory at prompt. Current displaying directory  is:  "+GlobalValues.displayDirectory); }
       public void actionPerformed(ActionEvent e) {
                           SwingUtilities.invokeLater(new Runnable() {
            @Override
           public void run() {  // run in  */
      GlobalValues.displayDirectory = !GlobalValues.displayDirectory;
      GlobalValues.scalalabMainFrame.getPromptJMenuItem().setText("Switches Display/Hide working directory at prompt. Current displaying directory  is:  "+GlobalValues.displayDirectory); 
      GlobalValues.scalalabMainFrame.scalalabConsole.displayPrompt();
            }
                           }
                           );
                
                    }
   }
 
 
 class consoleOutputConfigAction extends AbstractAction { 
     consoleOutputConfigAction()   {super("Switches Automatic checking for output Console overlap.  Current state of notOverlapTheConsoleFlag is:  "+GlobalValues.notOverlapTheConsoleOutput); }
       public void actionPerformed(ActionEvent e) {
                           SwingUtilities.invokeLater(new Runnable() {
            @Override
           public void run() {  // run in  */
      GlobalValues.notOverlapTheConsoleOutput = !GlobalValues.notOverlapTheConsoleOutput;
      GlobalValues.scalalabMainFrame.getConsoleOutputJMenuItem().setText("Switches Automatic checking for output Console overlap.  Current state of notOverlapTheConsoleFlag is:  "+GlobalValues.notOverlapTheConsoleOutput);
      GlobalValues.scalalabMainFrame.scalalabConsole.displayPrompt();
            }
                           }
                           );
                
                    }
   }
 
class browseJavaClassesAction extends AbstractAction {
       browseJavaClassesAction()  {super("Browse file system for specifyng new ScalaSci ClassPath component"); }
       
    @Override
       public void actionPerformed(ActionEvent e) {
                           SwingUtilities.invokeLater(new Runnable() {
           public void run() {  // run in  */
      
    JFileChooser  chooser = new JFileChooser(GlobalValues.workingDir);
    chooser.setDialogTitle("Browse file system for specifyng new ScalaSci ClassPath component");
    int retVal = chooser.showOpenDialog(GlobalValues.scalalabMainFrame);
    if (retVal == JFileChooser.APPROVE_OPTION) { 
      File selectedFile = chooser.getSelectedFile();
      String SelectedFileWithPath = selectedFile.getAbsolutePath();
      String SelectedFilePathOnly = SelectedFileWithPath.substring(0, SelectedFileWithPath.lastIndexOf(File.separatorChar));
      if (GlobalValues.ScalaSciClassPath.indexOf(SelectedFilePathOnly)==-1)  {
        GlobalValues.ScalaSciClassPathComponents.add(0,SelectedFilePathOnly);
        GlobalValues.ScalaSciClassPath = GlobalValues.ScalaSciClassPath+File.pathSeparator+SelectedFilePathOnly;
        GlobalValues.ScalaSciUserPaths.add(SelectedFilePathOnly);  // add to the user specified directories
        }
          // update also the ScalaSciClassPath property
      StringBuilder fileStr = new StringBuilder();
      Enumeration enumDirs = GlobalValues.ScalaSciClassPathComponents.elements();
      while (enumDirs.hasMoreElements())  {
         Object ce = enumDirs.nextElement();
         fileStr.append(File.pathSeparator+(String)ce.toString().trim());
    }
    GlobalValues.settings.setProperty("ScalaSciClassPathProp", fileStr.toString());
    
      ClassLoader parentClassLoader = getClass().getClassLoader();
      GlobalValues.extensionClassLoader = new  ExtensionClassLoader(GlobalValues.ScalaSciClassPath, parentClassLoader);
      
    
                    scalaExec.scalaLab.scalaLab.updateTree();
                    scalaExec.scalaLab.scalaLab.outerPane.revalidate();
    
                }
                     }
              });
                
     }
}
 

// this class permits the user to browse the filesystem and to append directories to the ScalaSciClassPath   
class browseScalaSciFilesAction extends AbstractAction {
       browseScalaSciFilesAction()  {super("Browse File System for specifying new ScalaSciClassPath component"); }
       
    @Override
       public void actionPerformed(ActionEvent e) {
                           SwingUtilities.invokeLater(new Runnable() {
            @Override
           public void run() {  // run in  */
                     
    JFileChooser  chooser = new JFileChooser(GlobalValues.workingDir);
    chooser.setDialogTitle("Browse file system and select your file to update ScalaSciClassPath to include it");
    int retVal = chooser.showOpenDialog(GlobalValues.scalalabMainFrame);
    
      if (retVal == JFileChooser.APPROVE_OPTION) {    // update the paths according to the selected file
      File selectedFile = chooser.getSelectedFile();  // the selected file
      String SelectedFileWithPath = selectedFile.getAbsolutePath();   // the full path of the selected file
      String SelectedFilePathOnly = SelectedFileWithPath.substring(0, SelectedFileWithPath.lastIndexOf(File.separatorChar)+1); // extract the path only
        
      int idx = -1; 
      // update structures for ScalaSciClassPath
      if (GlobalValues.ScalaSciClassPath !=null) 
          idx = GlobalValues.ScalaSciClassPath.indexOf(SelectedFilePathOnly);
      boolean appendPath = (GlobalValues.ScalaSciClassPath==null) || (idx == -1);
      if (appendPath)        
               {    // path not already exist in ScalaSciClassPath
        
          // append the new path to the ScalaSci's path
        scalaSciCommands.BasicCommands.appendClasspath(SelectedFilePathOnly);
               
          GlobalValues.ScalaSciUserPaths.add(SelectedFilePathOnly);  // append to the user specified path components for retrieving Scala classes    
            
          // rebuild the class path property (i.e. "ScalaSciClassPathProp") in order to account for the new path
          StringBuilder fileStr = new StringBuilder();
      Enumeration enumDirs = GlobalValues.ScalaSciClassPathComponents.elements();
      while (enumDirs.hasMoreElements())  {
         Object ce = enumDirs.nextElement();
         fileStr.append(File.pathSeparator+(String)ce.toString().trim());
    }
      GlobalValues.ScalaSciClassPath = fileStr.toString();   // the ScalaSci classpath as a String
      GlobalValues.settings.setProperty("ScalaSciClassPathProp", GlobalValues.ScalaSciClassPath);    // keep in property in order to be saved
      }   // path not already exist in ScalaSciClassPath
      
           
      // update structures for ScalaSciUserPaths
      if (GlobalValues.ScalaSciUserPaths.contains(SelectedFilePathOnly)==false)        
               {    // path not already exist in ScalaSciUserPaths
          GlobalValues.ScalaSciUserPaths.add(SelectedFilePathOnly);  // append to the ScalaSciUserPaths components for retrieving Scala classes
            
          // rebuild the ScalaSci User paths property (i.e. "ScalaSciUserPathsProp") in order to account for the new path
      StringBuilder fileStr = new StringBuilder();
      Enumeration enumDirs = GlobalValues.ScalaSciUserPaths.elements();
      while (enumDirs.hasMoreElements())  {
         Object ce = enumDirs.nextElement();
         fileStr.append(File.pathSeparator+(String)ce);
    }
      GlobalValues.settings.setProperty("ScalaSciUserPathsProp", fileStr.toString());    // keep in property in order to be saved
      }  // path not already exist in ScalaSciUserPaths
      
    scalaExec.scalaLab.scalaLab.updateTree();
    scalaExec.scalaLab.scalaLab.outerPane.revalidate();
            
     }  // update the paths according to the selected file
    }
                     
            
  });
                
 }
   
    
   class commandHistoryAction extends AbstractAction {
       commandHistoryAction()  {super("Displays the command history"); }
       
        @Override
                     public void actionPerformed(ActionEvent e) {
                           SwingUtilities.invokeLater(new Runnable() {
                            @Override
     public void run() {  // run in  EDT context */
                    scalaExec.scalaLab.commandHistory.loadCommandHistory(GlobalValues.scalalabCommandHistoryFile, GlobalValues.userConsole.previousCommands);  
               final JList  historyList = new JList(GlobalValues.userConsole.previousCommands);
               JPanel auxPanel = new JPanel();
               auxPanel.add(historyList);
               JScrollPane auxPane = new JScrollPane(auxPanel);
               JFrame  auxFrame = new JFrame("Command History");
               auxFrame.add(auxPane);
               auxFrame.setSize(300, 300);
               auxFrame.setLocation(100, 100);
               auxFrame.setVisible(true);
               
                historyList.addListSelectionListener(new        ListSelectionListener()
         {
            public void valueChanged(ListSelectionEvent event)
            {  
               Object[] values = historyList.getSelectedValues();

               StringBuilder text = new StringBuilder();
               for (int i = 0; i < values.length; i++)
               {  
                  String word = (String) values[i];
                  text.append(word);
                  text.append(" ");
               }
               
               // replace current command with next command
    	String textArea = GlobalValues.userConsole.getText();
    	int    pos1     = textArea.lastIndexOf("# ") + 2;
    	GlobalValues.userConsole.setText(textArea.substring(0,pos1)+text);
    	
    	// set cursor at the end of the text area
        GlobalValues.userConsole.setCaretPosition(GlobalValues.userConsole.getText().length());
            }
         });  // new ListSelectionListener

         
                            }  // run in EDT context
                          });  // new Runable()
                     }  // actionPerformed
                 }
}



   class controlMainToolBarAction extends AbstractAction {
           controlMainToolBarAction() {
               super("Show/Hide Main Toolbar");
           }
                    public void actionPerformed(ActionEvent e) {
                        GlobalValues.mainToolbarVisible = !GlobalValues.mainToolbarVisible;
                        GlobalValues.scalalabMainFrame.tabbedToolbars.setVisible(GlobalValues.mainToolbarVisible);
                    }
                }

class resetInterpreterAction extends AbstractAction {
           resetInterpreterAction() {
               super("Reset the Scala Interpreter state");
           }
                    public void actionPerformed(ActionEvent e) {
  GlobalValues.scalalabMainFrame.scalalabConsole.createInterpreterForClearAll();
                }
                    

 }
                
   
              
              
       
 
             
    
       
